package com.icoolkj.ms.rbac.feign;

import cn.hutool.core.util.ObjectUtil;
import com.icoolkj.ms.api.auth.bo.UserInfoInTokenBO;
import com.icoolkj.ms.api.rbac.dto.ClearUserPermissionsCacheDTO;
import com.icoolkj.ms.api.rbac.feign.PermissionFeignClient;
import com.icoolkj.ms.common.core.constant.Auth;
import com.icoolkj.ms.common.core.enums.ResponseEnum;
import com.icoolkj.ms.common.core.feign.FeignInsideAuthConfig;
import com.icoolkj.ms.common.core.response.ServerResponseEntity;
import com.icoolkj.ms.rbac.bo.UriPermissionBO;
import com.icoolkj.ms.rbac.service.ISysPermissionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @author icoolkj
 * @version 1.0
 * @description
 * @createDate 2025/02/11 11:00
 */
@RestController
public class PermissionFeignController implements PermissionFeignClient {

    private static final Logger logger = LoggerFactory.getLogger(PermissionFeignController.class);

    @Autowired
    private ISysPermissionService iSysPermissionService;

    /**
     * 判断是否包含权限
     *
     * @param authorities 权限列表
     * @param permission 权限字符串
     * @return 用户是否具备某权限
     */
    public boolean hasPermi(Collection<String> authorities, String permission)
    {
        return authorities.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Auth.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
    }

    // 获取当前用户拥有的权限
    private List<String> getUserPermissions(UserInfoInTokenBO userInfoInTokenBO) {
        if (userInfoInTokenBO == null) {
            return Collections.emptyList();
        }
        return iSysPermissionService.getUserMenuPermissions(userInfoInTokenBO.getUserId(), userInfoInTokenBO.getUserType());
    }

    @Override
    @GetMapping(value = Auth.CHECK_PERMI_AND)
    public ServerResponseEntity<Boolean> checkPermiAnd(@RequestParam("userId") Long userId,
                                                       @RequestParam("userType") String userType,
                                                       @RequestParam String... permissions) {
        try {
            // 目前当前用户拥有的权限
            List<String> permissionList = iSysPermissionService.getUserMenuPermissions(userId, userType);
            for (String permission : permissions) {
                if (!hasPermi(permissionList, permission)){
                    return ServerResponseEntity.success(Boolean.FALSE);
                }
            }
            return ServerResponseEntity.success(Boolean.TRUE);
        } catch (Exception e) {
            // 记录日志
            logger.error("Error checking permissions (AND logic)", e);
            return ServerResponseEntity.fail("Error checking permissions");
        }
    }


    @Override
    @GetMapping(value = Auth.CHECK_PERMI_OR)
    public ServerResponseEntity<Boolean> checkPermiOr(@RequestParam("userId") Long userId,
                                                      @RequestParam("userType") String userType,
                                                      @RequestParam String... permissions){
        try {
            // 目前当前用户拥有的权限
            List<String> permissionList = iSysPermissionService.getUserMenuPermissions(userId, userType);
            for (String permission : permissions) {
                if (hasPermi(permissionList, permission)) {
                    return ServerResponseEntity.success(Boolean.TRUE);
                }
            }
            return ServerResponseEntity.success(permissions.length == 0);
        } catch (Exception e) {
            logger.error("Error checking permissions (OR logic)", e);
            return ServerResponseEntity.fail("Error checking permissions");
        }
    }


    @Override
    @GetMapping(value = Auth.CHECK_RBAC_URI)
    public ServerResponseEntity<Boolean> checkPermission(@RequestParam("userId") Long userId,
                                                         @RequestParam("userType") String userType,
                                                         @RequestParam("uri") String uri,
                                                         @RequestParam("isAdmin") Integer isAdmin,
                                                         @RequestParam("method") Integer method) {
        // 目前当前用户拥有的权限
        List<String> permissionList = iSysPermissionService.getUserMenuPermissions(userId, userType);

        // uri,方法对应的权限 map
        List<UriPermissionBO> uriPermissions = iSysPermissionService.listUriPermissionInfo(userType);

        AntPathMatcher pathMatcher = new AntPathMatcher();

        for (UriPermissionBO uriPermission : uriPermissions) {
            // uri + 请求方式匹配
            if (pathMatcher.match(uriPermission.getUri(), uri) && ObjectUtil.equals(uriPermission.getMethod(), method)) {
                // uri 用户有这个权限
                if (permissionList.contains(uriPermission.getPermission())) {
                    return ServerResponseEntity.success(Boolean.TRUE);
                }
                else {
                    return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
                }
            }
        }

        // uri 没有匹配到，说明uri不需要权限，直接校验成功
        return ServerResponseEntity.success(Boolean.TRUE);
    }


    @Override
    @PostMapping(value = FeignInsideAuthConfig.FEIGN_INSIDE_URL_PREFIX + "/insider/permission/clearUserPermissionsCache")
    public ServerResponseEntity<Void> clearUserPermissionsCache(ClearUserPermissionsCacheDTO clearUserPermissionsCacheDTO) {
        iSysPermissionService.clearUserPermissionsCache(clearUserPermissionsCacheDTO.getUserId(), clearUserPermissionsCacheDTO.getUserType());
        return ServerResponseEntity.success();
    }

    @Override
    @GetMapping(value = FeignInsideAuthConfig.FEIGN_INSIDE_URL_PREFIX + "/insider/permission/getUserMenuPermissions")
    public List<String> getUserMenuPermissions(@RequestParam("userId") Long userId, @RequestParam("userType") String userType) {
        return iSysPermissionService.getUserMenuPermissions(userId, userType);
    }

    @Override
    @GetMapping(value = FeignInsideAuthConfig.FEIGN_INSIDE_URL_PREFIX + "/insider/permission/selectRoleKeyListByUserId")
    public List<String> selectRoleKeyListByUserId(@RequestParam("userId") Long userId, @RequestParam("userType") String userType) {
        return iSysPermissionService.selectRoleKeyListByUserId(userId, userType);
    }

}
